#include <hardware/motor/motor.h>

// BasicStepperDriver(short steps, short dir_pin, short step_pin, short enable_pin);
BasicStepperDriver stepper(MOTOR_STEPS, DIR, STEP, SLEEP);
// rpm每分钟转多少圈，默认值为2
// 假如1分钟转一圈，一圈需要转动200*16=3200次，3200÷60≈53，也就是频率设置为53HZ就可以实现1分钟转一圈。
// 但是频率范围是100-60000，所以默认值为2
double rpm = INITIAL_RPM;
// 电机驱动方向 0-正转  1-反转  2-关闭  
char motorDir = 2;
//周期性执行快速翻转电机flipMotor的Ticker
Ticker flipper;

void initMotor()
{
  stepper.begin(RPM, MICROSTEPS);
  pinMode(SLEEP, OUTPUT);
  // digitalWrite设置引脚输出状态：高电平 低电平
  //睡眠，接低电平则电机断电，用手拧可以自由转动
  digitalWrite(SLEEP, LOW);
  // 该功能用于改变PWM频率，默认是1kHZ。 有效范围是100-60000。
  //53HZ可以实现每分钟转一圈，53*INITIAL_RPM HZ可以实现每分钟转INITIAL_RPM圈
  //注意：analogWriteFreq(0)异常会使ESP8266重启
  analogWriteFreq(53 * INITIAL_RPM);
  // analogWriteRange(new_range)    该功能用于改变PWMRANGE数值---改变引脚读写的数据。
  // PWMRANGE数值越大，精度越高，这是为什么呢？举例如下：
  // PWMRANGE=2,占空比可以为0、1/2、1；PWMRANGE=3,占空比可以为0、1/3、2/3、1；
  analogWriteRange(3);
  // analogWrite用于输出PWM（脉宽调制）信号，通过快速切换高低电平来模拟模拟信号，适用于LED调光、直流电机调速、步进电机限流。
  // analogWrite(pin,val)  pin：要启用软件PWM的GPIO引脚, val：数值，一般在0到PWMRANGE范围，默认PWMRANGE是1023
  // analogWrite()默认的频率是1khz，默认PWMRANGE数值是1023
  // 占空比是指在一个周期内，脉冲信号处于高电平(或有效电平)的时间与整个周期时间的比值。
  // analogWrite(STEP, 0)表示禁止输出PWD信号
  analogWrite(STEP, 0);
}

void powerMotor(unsigned char direction, unsigned int rpm) // 驱动电机
{
  digitalWrite(DIR, direction);
  analogWriteFreq(53 * rpm);
  // analogWriteRange(3)
  // 表示给STEP这个角写入占空比为1/3的pwm波
  // 步进电机的速度主要由PWM信号频率控制‌，与占空比无直接关联。
  analogWrite(STEP, 1);
}

void accelerateMotor(unsigned char direction) // 加速度驱动电机
{
  powerMotor(direction, rpm);
  if (rpm < RPM)
  {
    rpm += INCREASE_RPM;
    if (rpm > RPM)
    {
      rpm = RPM;
    }
  }
}

void closeMotor()
{
  rpm = INITIAL_RPM;
  motorDir = 2;
  analogWriteFreq(53 * INITIAL_RPM);
  analogWrite(STEP, 0);
  digitalWrite(SLEEP, LOW);
  flipper.detach();
}

void flipMotor()
{
  if (motorDir == 0)
  {
    if (getStatusForForward() == 1)
    {
      //睡眠，接高电平则电机上电，用手拧不动。
      digitalWrite(SLEEP, HIGH);
      // 正转
      accelerateMotor(0);
    }
    else
    {
      closeMotor();
    }
  }
  else if (motorDir == 1)
  {
    if (getStatusForReverse() == 1)
    {
      digitalWrite(SLEEP, HIGH);
      // 反转
      accelerateMotor(1);
    }
    else
    {
      closeMotor();
    }
  }
}

void tickerMotor(unsigned char dir)
{
  rpm = INITIAL_RPM;
  motorDir = dir;
  flipper.attach_ms(10, flipMotor);
  return;
}